/*
 *  NetworkUtil.h
 *  Ringer
 *
 *  Created by Ian Pye on 12/24/07.
 *  Copyright 2007 TriceratopsPowered. All rights reserved.
 *  Ideas here --> limit these to only those implemented -- logic goes in RingerFS
 */

#ifndef __RINGER_NETWORK_H__
#define __RINGER_NETWORK_H__

// basic init utils
bool ringer_init_network(ringer::RingerNetworkArgs*, bool disable_clientServer = false);
bool ringer_close_network();

// testing opts
bool ringer_client_ping();
int ringer_client_add(int, int);

// Search opts
int ringer_client_search(std::set<ringer::rpath_t>& results, ringer::RingerSearch& terms);

// data opts
int read_network_file(const char*, size_t size, off_t offset);
bool ping_rnode_owner(const char *path);
bool initiate_send_block(const char *path, size_t size, off_t offset);
bool initiate_send_block(const ringer::UserInfo& ui, const char *path, size_t size, off_t offset);

// MetaData opts
void ringer_client_put(ringer::RNode &);
void ringer_client_get(const char *, ringer::RNode &);
void ringer_client_remove(const char *);

// permission ops
bool ringer_client_get_read(const char *);
bool ringer_client_get_read(const char *, const ringer::UserInfo& ui);
void ringer_client_end_read(const char *);
bool ringer_client_get_write(const char *);
bool ringer_client_get_write(const char *, const ringer::UserInfo& ui);
void ringer_client_end_write(const char *);

// SimHash Stuff
float find_simularity(const std::vector<ringer::simresult_t>&, const std::vector<ringer::simresult_t>&);

// getters and setters

// currently nothing I really want to put here
namespace ringer {
  static UserInfo g_clientUser;
  //static boost::shared_ptr<facebook::thrift::transport::TTLSClientAuthentication> 
  //    g_authHandler(new facebook::thrift::transport::TTLSClientAuthentication());
  //static boost::shared_ptr<facebook::thrift::transport::TTLSServerAuthentication> 
  //    g_serverAuthHandler(new facebook::thrift::transport::TTLSServerAuthentication());
} // end ringer namespace

// Macro defineing how our clients work.
/*
#define RINGER_GET_CLIENT(host, port, trans, client, auth_hand) \
{ \
shared_ptr<TTransport> new_socket(new TTLSSocket(host, port, *auth_hand)); \
shared_ptr<TTransport> new_transport(new TBufferedTransport(new_socket)); \
shared_ptr<TProtocol> new_protocol(new TBinaryProtocol(new_transport)); \
shared_ptr<RingerMetaServerClient> new_client(new RingerMetaServerClient(new_protocol)); \
client.swap(new_client); \
trans.swap(new_transport); \
} 

// Likewise, this defines how we get a server.
#define RINGER_GET_SERVER(port, server_impl, serv, auth_hand_server) \
{  \
shared_ptr<TProcessor> new_processor(new RingerMetaServerProcessor(server_impl)); \
shared_ptr<TServerTransport> new_serverTransport(new TTLSServerSocket(port, *auth_hand_server)); \
shared_ptr<TTransportFactory> new_transportFactory(new TBufferedTransportFactory()); \
shared_ptr<TProtocolFactory> new_protocolFactory(new TBinaryProtocolFactory()); \
shared_ptr<TServer> new_server(new TThreadedServer(new_processor, new_serverTransport, \
new_transportFactory, new_protocolFactory)); \
serv.swap(new_server); \
} 
*/
/*
#define RINGER_GET_SERVER(port, server_impl, serv) \
{  \
shared_ptr<TProcessor> new_processor(new RingerMetaServerProcessor(server_impl)); \
shared_ptr<TServerTransport> new_serverTransport(new TTLSServerSocket(port, *g_serverAuthHandler)); \
shared_ptr<TTransportFactory> new_transportFactory(new TBufferedTransportFactory()); \
shared_ptr<TProtocolFactory> new_protocolFactory(new TBinaryProtocolFactory()); \
shared_ptr<TServer> new_server(new TSimpleServer(new_processor, new_serverTransport, \
new_transportFactory, new_protocolFactory)); \
serv.swap(new_server); \
}*/

// BELOW, WE ARE NOT USING ANY ENCRYPTION
// Macro defineing how our clients work.
/*
#define RINGER_GET_CLIENT(host, port, trans, client, auth_hand) \
{ \
shared_ptr<TTransport> new_socket(new TSocket(host, port)); \
shared_ptr<TTransport> new_transport(new TBufferedTransport(new_socket)); \
shared_ptr<TProtocol> new_protocol(new TBinaryProtocol(new_transport)); \
shared_ptr<RingerMetaServerClient> new_client(new RingerMetaServerClient(new_protocol)); \
client.swap(new_client); \
trans.swap(new_transport); \
} 

// Likewise, this defines how we get a server.
#define RINGER_GET_SERVER(port, server_impl, serv, auth_hand_server) \
{  \
shared_ptr<TProcessor> new_processor(new RingerMetaServerProcessor(server_impl)); \
shared_ptr<TServerTransport> new_serverTransport(new TServerSocket(port)); \
shared_ptr<TTransportFactory> new_transportFactory(new TBufferedTransportFactory()); \
shared_ptr<TProtocolFactory> new_protocolFactory(new TBinaryProtocolFactory()); \
shared_ptr<TServer> new_server(new TThreadedServer(new_processor, new_serverTransport, \
new_transportFactory, new_protocolFactory)); \
serv.swap(new_server); \
}
*/

// BELOW, WE ARE USING OPENSSL
// Macro defineing how our clients work.
#define RINGER_GET_CLIENT(host, port, trans, client, trustStore) \
{ \
shared_ptr<TTransport> new_socket(new TSSLSocket(host, port, trustStore)); \
shared_ptr<TTransport> new_transport(new TBufferedTransport(new_socket)); \
shared_ptr<TProtocol> new_protocol(new TBinaryProtocol(new_transport)); \
shared_ptr<RingerMetaServerClient> new_client(new RingerMetaServerClient(new_protocol)); \
client.swap(new_client); \
trans.swap(new_transport); \
} 

// Likewise, this defines how we get a server.
#define RINGER_GET_SERVER(port, server_impl, serv, publicKey, privateKey) \
{  \
shared_ptr<TProcessor> new_processor(new RingerMetaServerProcessor(server_impl)); \
shared_ptr<TServerTransport> new_serverTransport(new TSSLServerSocket(port, publicKey, privateKey)); \
shared_ptr<TTransportFactory> new_transportFactory(new TBufferedTransportFactory()); \
shared_ptr<TProtocolFactory> new_protocolFactory(new TBinaryProtocolFactory()); \
shared_ptr<TServer> new_server(new TThreadedServer(new_processor, new_serverTransport, \
new_transportFactory, new_protocolFactory)); \
serv.swap(new_server); \
}

#endif //__RINGER_NETWORK_H__
